package com.kevin.algorithm;

import com.kevin.model.Location;
import com.kevin.utils.DistanceUtil;
import com.kevin.utils.PointsRep;

import java.util.List;

/**
 * @Description: 路径中加点算法
 *
 * 待加点到相邻两个点距离最近
 *
 * @author kevin
 * @version V1.0
 * @date 2019/3/5 11:03
 **/
public class InsertRoute implements AlgorithmStrategy{
    /**
     * 需要加点的一维下标索引
     */
    private int x = -1;
    /**
     * 需要加点的二维下标索引
     */
    private int y = -1;
    /**
     * 需要加点到相邻两个点的距离和
     */
    private double distance = 0;

    /**
     * @Description: 执行加点算法
     *
     * @param
     * @return
     **/
    @Override
    public Location[][] execute(PointsRep pointsRep) {
        List<List<Location>> list = pointsRep.getTwoDimentionList();

        /**
         * 进行插单位置计算
         */
        handleInsertRoute(list,pointsRep.getLocation());

        /**
         * 插点
         */
        if(x!=-1 && y!=-1){
            list.get(x).add(y,pointsRep.getLocation());
        }

        /**
         * 将list封装成二维数组
         */
        int maxSize = 0;
        for(int i=0;i<list.size();i++){
            if(list.get(i).size() > maxSize){
                maxSize = list.get(i).size();
            }
        }
        Location[][] result = new Location[list.size()][maxSize];
        for(int i=0;i<list.size();i++){
           for(int j=0;j<list.get(i).size();j++){
               result[i][j] = list.get(i).get(j);
           }
        }


        return result;
    }

    private void handleInsertRoute(List<List<Location>> twoDimentionList,Location location){
        for(int i=0;i<twoDimentionList.size();i++){
            /**
             * 判断队列是否大于一个点
             */
            if(twoDimentionList.get(i).size() > 1){
                for(int j=1;j<twoDimentionList.get(i).size();j++){
                    double currDisBefore = Double.valueOf(DistanceUtil.algorithm(twoDimentionList.get(i).get(j-1).getLon(),twoDimentionList.get(i).get(j-1).getLat(),location.getLon(),location.getLat()));
                    double currDisAfter = Double.valueOf(DistanceUtil.algorithm(twoDimentionList.get(i).get(j).getLon(),twoDimentionList.get(i).get(j).getLat(),location.getLon(),location.getLat()));
                    double currDis = currDisBefore + currDisAfter;

                    if(x == -1 || distance > currDis){
                        x = i;
                        y = j;
                        distance = currDis;
                    }
                }
            }else if(twoDimentionList.get(i).size() == 1){
                double currDis = Double.valueOf(DistanceUtil.algorithm(twoDimentionList.get(i).get(0).getLon(),twoDimentionList.get(i).get(0).getLat(),location.getLon(),location.getLat()));

                if(x == -1 || distance > currDis){
                    x = i;
                    y = 0;
                    distance = currDis;
                }
            }
        }
    }
}
